package web

import (
	"binterfaces/ihttp"
	"binterfaces/ilogger"
	"embed"
	"net/http"
	_ "net/http"
	"net/url"
	"sync"
)

type (
	// QuickWebContext 上下文
	QuickWebContext struct {
		log                ilogger.ILogger
		request            ihttp.IHttpRequest
		response           ihttp.IHttpResponse
		formCache          url.Values
		queryCache         url.Values
		attr               map[string]any
		lock               sync.Mutex
		maxMultipartMemory int64
	}
)

func NewContext(log ilogger.ILogger) *QuickWebContext {
	return &QuickWebContext{
		log:  log,
		attr: make(map[string]any),
	}
}

/** ====================== IHttpContext ============================== */

func (q *QuickWebContext) Log() ilogger.ILogger {
	return q.log
}

func (q *QuickWebContext) Build(response http.ResponseWriter, request *http.Request) ihttp.IHttpContext {
	q.request = NewHttpRequest(q.log, request)
	q.response = NewHttpResponse(q.log, response)
	q.formCache = nil
	q.queryCache = nil
	q.attr = nil
	return q
}

func (q *QuickWebContext) Query() ihttp.IQuery {
	return q.request.Query()
}

func (q *QuickWebContext) Param() ihttp.IParam {
	return q.request.Param()
}

func (q *QuickWebContext) Body() ihttp.IBody {
	return q.request.Body()
}

func (q *QuickWebContext) Request() ihttp.IHttpRequest {
	return q.request
}

func (q *QuickWebContext) Response() ihttp.IHttpResponse {
	return q.response
}

func (q *QuickWebContext) Path() string {
	return q.request.Path()
}

func (q *QuickWebContext) Method() string {
	return q.request.Method()
}

func (q *QuickWebContext) Set(key string, value any) {
	q.lock.Lock()
	defer q.lock.Unlock()
	q.attr[key] = value
}

func (q *QuickWebContext) Get(key string) (value any, exist bool) {
	q.lock.Lock()
	defer q.lock.Unlock()
	value, exist = q.attr[key]
	return
}

/** ====================== IHttpResponse ============================== */

func (q *QuickWebContext) Header(key, value string) {
	q.response.Header(key, value)
}

func (q *QuickWebContext) Status(code int) {
	q.response.Status(code)
}

func (q *QuickWebContext) Json(code int, data any) {
	q.response.Json(code, data)
}

/** ====================== StaticFile ============================== */

func (q *QuickWebContext) File(filepath string) {
	http.ServeFile(q.response.Response(), q.request.Request(), filepath)
}

func (q *QuickWebContext) FileFromFS(filepath string, fs http.FileSystem) {
	defer func(old string) {
		q.request.Request().URL.Path = old
	}(q.request.Request().URL.Path)

	q.request.Request().URL.Path = filepath

	http.FileServer(fs).ServeHTTP(q.response.Response(), q.request.Request())
}

func (q *QuickWebContext) StaticFile(path, root string) {

}

func (q *QuickWebContext) StaticFS(path string, fs http.FileSystem) {

}

func (q *QuickWebContext) StaticEmbed(path, notfoundPath string, fs embed.FS) {

}
